package com.jy.unkown.http;

import android.os.Build;
import android.os.Handler;
import android.os.Looper;
import android.text.TextUtils;

import androidx.annotation.Keep;


import com.google.gson.Gson;
import com.jiayou.CommonHost;
import com.jy.common.InitCommonData;
import com.jy.common.exception.AppException;
import com.jy.common.net.VPN;
import com.jy.http.JsonCallBack;
import com.jy.utils.cache.CacheManager;
import com.jy.utils.um.Report;
import com.jy.utils.utils.LogUtils;
import com.jy.utils.utils.MD5;
import com.jy.utils.utils.PhoneUtils;

import org.json.JSONException;
import org.json.JSONObject;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.net.Proxy;
import java.net.URLEncoder;
import java.util.Map;
import java.util.concurrent.TimeUnit;

import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.MediaType;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;

public class OkGo {
    public static final String TAG = "---OkGo---";
    private static volatile OkGo instance;
    public static final long TIME_OUT = 10_000L;

    private final OkHttpClient okHttpClient;
    private final Handler handler;
    private final Gson gson;

    private static final MediaType jsonMediaType = MediaType.parse("application/json; charset=utf-8");

    public OkGo() {
        OkHttpClient.Builder builder = new OkHttpClient.Builder();

        builder.connectTimeout(TIME_OUT, TimeUnit.MILLISECONDS)
                .readTimeout(TIME_OUT, TimeUnit.MILLISECONDS)
                .writeTimeout(TIME_OUT, TimeUnit.MILLISECONDS);

        if (CommonHost.isDebug()) {
            builder.addInterceptor(new LoggerInterceptor(null, true));
        } else {
            builder.proxy(Proxy.NO_PROXY);
        }

        this.okHttpClient = builder.build();

        this.handler = new Handler(Looper.getMainLooper());
        this.gson = new Gson();
    }

    /**
     * 取消请求
     *
     * @param tag
     */
    public void cancelTag(Object tag) {
        if (tag != null) {
            for (Call call : okHttpClient.dispatcher().queuedCalls()) {
                if (tag.equals(call.request().tag())) {
                    call.cancel();
                }
            }
            for (Call call : okHttpClient.dispatcher().runningCalls()) {
                if (tag.equals(call.request().tag())) {
                    call.cancel();
                }
            }
        }
    }

    @Keep
    public static OkGo instance() {
        if (instance == null) {
            synchronized (OkGo.class) {
                if (instance == null) {
                    instance = new OkGo();
                }
            }
        }
        return instance;
    }

    public void get(String url) {
        get(null, url, null, null);
    }

    public <T> void get(String url, com.jy.http.JsonCallBack<T> callBack) {
        get(null, url, null, callBack);
    }

    public <T> void get(Object tag, String url, com.jy.http.JsonCallBack<T> callBack) {
        get(tag, url, null, callBack);
    }

    public <T> void get(Object tag, String url, Map<String, Object> data, com.jy.http.JsonCallBack<T> callBack) {
        Request.Builder builder = new Request.Builder();

        if (tag != null) {
            builder.tag(tag);
        }

        String content;
        if (data != null && !data.isEmpty()) {
            JSONObject jo = new JSONObject();
            StringBuilder urlBuilder = new StringBuilder(url);
            urlBuilder.append("?");
            for (Map.Entry<String, Object> map : data.entrySet()) {
                urlBuilder.append(map.getKey()).append("=").append(map.getValue()).append("&");

                try {
                    jo.put(map.getKey(), map.getValue());
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
            url = urlBuilder.toString();
            url = url.substring(0, url.length() - 1);

            content = jo.toString();
        } else {
            content = "";
        }
        builder.url(url);

        exec(content, builder, callBack);
    }
    @Keep
    public <T> void post(String url, JSONObject data, com.jy.http.JsonCallBack<T> callBack) {
        post(null, url, data, callBack);
    }

    public void post(String url, JSONObject data) {
        post(null, url, data, null);
    }
    public <T> void post(Object tag, String url, JSONObject data, com.jy.http.JsonCallBack<T> callBack) {

        RequestBody postBody;
        String content;
        if (data == null) {
            content = "";
        } else {
            content = data.toString();
        }



        postBody = RequestBody.create(jsonMediaType, content);

        Request.Builder builder = new Request.Builder();

        builder.url(url);

        builder.post(postBody);

        if (tag != null) {
            builder.tag(tag);
        }

        exec(content, builder, callBack);
    }


    /**
     * 开始请求
     *
     * @param builder
     * @param callBack
     */
    private <T> void exec(String content, Request.Builder builder, com.jy.http.JsonCallBack<T> callBack) {
        if (!CommonHost.isDebug()) {
            if (isWifiProxy()|| VPN.isVpnUsed()==1) {
                if (callBack != null) {
                    callBack.error(new AppException("操作失败"));
                }
                return;
            }
        }


        okHttpClient.newCall(builder.build()).enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {
                try {
                    e.printStackTrace();
                    if (callBack != null) {
                        if (e.toString().contains("closed")) {
                            // 取消请求
                        } else {
                            handler.post(() -> {
                                // UnknownHostException  SocketTimeoutException
                                callBack.error(new Exception("操作失败～"));
                            });
                        }
                    }
                } catch (Exception err) {
                    err.printStackTrace();
                }
            }

            @Override
            public void onResponse(Call call, Response response) throws IOException {
                try {
                    String body = response.body().string();
                    if (callBack != null) {
                        handler.post(() -> {
                            if (response.isSuccessful()) {
                                try {
                                    Object res = parseT(body, callBack);
                                    if (res == null) {
                                        callBack.error(new Exception("操作失败(-1)"));
                                    } else {
                                        callBack.success((T) res);
                                    }
                                } catch (Exception e) {
                                    e.printStackTrace();
                                    callBack.error(new Exception("操作失败(-2)"));
                                }
                            } else {
                                callBack.error(new Exception("操作失败~"));
                            }
                        });
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                    if (callBack != null) {
                        handler.post(() -> {
                            callBack.error(e);
                        });
                    }
                }
            }
        });
    }

    private <T> T parseT(String body, JsonCallBack callBack) throws Exception {
        Type genType = callBack.getClass().getGenericSuperclass();
        Type type = ((ParameterizedType) genType).getActualTypeArguments()[0];

        LogUtils.showLog(TAG, "ParameterizedType: " + type.toString());
        return gson.fromJson(body, type);

//        if (type instanceof ParameterizedType) {
//            String typeStr = type.toString().toLowerCase();
//            if (typeStr.contains("jsonobject")) {
//                return (T) new JSONObject(body);
//            } else if (typeStr.contains("jsonarray")) {
//                return (T) new JSONArray(body);
//            } else if (typeStr.contains("string")) {
//                return (T) body;
//            }
//        } else if (type instanceof Class) {
//            if (type == String.class) {
//                return (T) body;
//            } else if (type == JSONObject.class) {
//                return (T) new JSONObject(body);
//            } else if (type == JSONArray.class) {
//                return (T) new JSONArray(body);
//            } else {
//                return gson.fromJson(body, type);
//            }
//        } else {
//            return gson.fromJson(body, type);
//        }
//
//        return gson.fromJson(body, type);
    }

    private boolean isOpenProxy = false;
    private long lastCheckProxyTime = 0L;

    /**
     * 是否开启代理
     *
     * @return
     */
    private boolean isWifiProxy() {
        if (System.currentTimeMillis() - lastCheckProxyTime < 5000) {
            return isOpenProxy;
        }

        lastCheckProxyTime = System.currentTimeMillis();

        try {
            String proxyAddress;
            int proxyPort;

            proxyAddress = System.getProperty("http.proxyHost");
            String portStr = System.getProperty("http.proxyPort");
            proxyPort = Integer.parseInt((portStr != null ? portStr : "-1"));

            isOpenProxy = (!TextUtils.isEmpty(proxyAddress)) && (proxyPort != -1);
        } catch (Exception e) {
            e.printStackTrace();
        }

        return isOpenProxy;
    }
}
